#pragma once
#include <glm/glm.hpp>

// lib
#include <glm/gtc/matrix_transform.hpp>

class CORE_API Camera
{
public:
  Camera() = default;
  Camera(Camera &camera);
  Camera(float fov, float aspectRatio, float nearClip, float farClip);

  static Ref<Camera> CreateDefault();

  void SetPosition(const glm::vec3 &position);
  void SetRotation(const glm::vec3 &rotation);
  void SetAspectRatio(float aspectRatio);
  void SetFov(float fov);
  void SetZNear(float nearClip);
  void SetZFar(float farClip);

  glm::vec3 &GetPosition() { return m_position; }
  glm::vec3 &GetRotation() { return m_rotation; }
  float GetAspectRatio() const { return m_aspectRatio; }
  float GetFov() const { return m_FOV; }
  float GetZNear() const { return m_nearClip; }
  float GetZFar() const { return m_farClip; }

  const glm::mat4 &GetProjectionMatrix() const { return m_projectionMatrix; }
  const glm::mat4 &GetViewMatrix() const { return m_viewMatrix; }
  const glm::mat4 &GetViewProjectionMatrix() const { return m_viewProjectionMatrix; }

  const glm::vec3 &GetRight() const { return m_right; }
  const glm::vec3 &GetUp() const { return m_up; }
  const glm::vec3 &GetForward() const { return m_forward; }
  const glm::vec3 &GetLookAt() const { return m_lookAt; }

private:
  void RecalculateViewMatrix();
  void RecalculateProjectionMatrix();

  float m_FOV = 45.f;
  float m_aspectRatio = 1.334f;
  float m_nearClip = 0.1f;
  float m_farClip = 100.f;

  glm::vec3 m_right;
  glm::vec3 m_up;
  glm::vec3 m_forward;
  glm::vec3 m_lookAt;

  glm::mat4 m_projectionMatrix;
  glm::mat4 m_viewMatrix;
  glm::mat4 m_viewProjectionMatrix;

  glm::vec3 m_position = {0.0f, 0.0f, 0.0f};
  glm::vec3 m_rotation = {0.0f, 0.0f, 0.0f};
};